(in-package :procemu)

(defclass arithmetic-instruction (instruction)
  ()
  (:documentation "A binary arithmetic instruction"))

(defmacro define-arithmetic-instruction (name function)
  "Define an arithmetic operation with a given name which applies a
named function to two locations"
  `(progn
    (defclass ,name (arithmetic-instruction)
      ((source :documentation "The location to be used as the source")
       (destination :documentation "The location to be used as the
destination")))
    (defmethod perform ((instruction ,name) (cpu cpu))
      (with-slots (source destination) instruction
	(setf (location cpu destination)
	      (,function (location cpu destination)
			 (location cpu source)))))))

(define-arithmetic-instruction add +)
(define-arithmetic-instruction sub -)
(define-arithmetic-instruction mul *)
(define-arithmetic-instruction div /)

(defmethod print-object ((instruction arithmetic-instruction) stream)
  (print-unreadable-object (instruction stream :type t)
    (handler-case
	(with-slots (source destination) instruction
	  (format stream "~A ~A"
		  (location-string destination)
		  (location-string source)))
      (unbound-slot ()
	(format stream "INSANE")))))